﻿using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioFuncionario : IRepositorioFuncionario
    {
        public Funcionario Inserir(Funcionario funcionario)
        {
            funcionario.DataDemissao = funcionario.DataDemissao.HasValue
                                        ? funcionario.DataDemissao.GetValueOrDefault().Date
                                        : funcionario.DataDemissao;
            funcionario.DataUltimoReajuste = funcionario.DataUltimoReajuste.HasValue
                                                ? funcionario.DataUltimoReajuste.GetValueOrDefault().Date
                                                : funcionario.DataUltimoReajuste;

            GerenciadorBDConfigs.Instance.SessaoAtual().Save(funcionario);
            return funcionario;
        }

        public Funcionario Atualizar(Funcionario funcionario)
        {
            Funcionario tmpFuncionario = ObterPorId(funcionario.FuncionarioId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpFuncionario.Codigo = funcionario.Codigo;
            tmpFuncionario.Cargo = funcionario.Cargo;
            tmpFuncionario.DataContratacao = funcionario.DataContratacao.Date;
            tmpFuncionario.DataDemissao = funcionario.DataDemissao.HasValue
                                            ? funcionario.DataDemissao.GetValueOrDefault().Date 
                                            : funcionario.DataDemissao;
            tmpFuncionario.DataUltimoReajuste = funcionario.DataUltimoReajuste.HasValue
                                                    ? funcionario.DataUltimoReajuste.GetValueOrDefault().Date
                                                    : funcionario.DataUltimoReajuste;
            tmpFuncionario.PercentualUltimoReajuste = funcionario.PercentualUltimoReajuste;
            tmpFuncionario.Salario = funcionario.Salario;
            tmpFuncionario.SalarioAnterior = funcionario.SalarioAnterior;
            tmpFuncionario.Setor = funcionario.Setor;
            tmpFuncionario.Pessoa = funcionario.Pessoa;
            tmpFuncionario.Observacao = funcionario.Observacao;

            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpFuncionario);
            return tmpFuncionario;
        }

        public void Excluir(Funcionario funcionario)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(funcionario);
        }

        public IList<Funcionario> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario));
            return criteria.List<Funcionario>() as List<Funcionario>;
        }

        public Funcionario ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Funcionario>(id);
        }

        public Funcionario ObterPorCodigo(string codigo)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
                .Add(Restrictions.Eq("Codigo",codigo));
            return criteria.UniqueResult<Funcionario>();
        }

        public IList<Funcionario> ObterPorCargo(int inicio, int quantidade, int quantidadeMinima, Cargo cargo)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            IList<Funcionario> list;
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
            .SetFirstResult(inicio).SetMaxResults(quantidade);
            criteria.Add(Restrictions.Eq("Cargo",cargo));
            return criteria.List<Funcionario>() as List<Funcionario>;
        }

        public IList<Funcionario> ObterPorSetor(int inicio, int quantidade, int quantidadeMinima, Setor setor)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            IList<Funcionario> list;
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
            .SetFirstResult(inicio).SetMaxResults(quantidade);
            criteria.Add(Restrictions.Eq("Setor", setor));
            return criteria.List<Funcionario>() as List<Funcionario>;
        }

        public IList<Funcionario> ObterTodos(int inicio, int quantidade, int quantidadeMinima, string codigo, string descricao, string cargoCodigo, string cargoDescricao, string setorCodigo, string setorDescricao, decimal previsaoSalarialDe, decimal previsaoSalarialAte, decimal salarioAnteriorDe, decimal salarioAnteriorAte, decimal percentualUltimoReajusteDe, decimal percentualUltimoReajusteAte, DateTime? ultimoReajusteDe, DateTime? ultimoReajusteAte, DateTime? contratacaoDe, DateTime? contratacaoAte, DateTime? demissaoDe, DateTime? demissaoAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            IList<Funcionario> list;
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
            .SetFirstResult(inicio).SetMaxResults(quantidade);

            if (!string.IsNullOrEmpty(codigo))
            {
                criteria.Add(Restrictions.Eq("Codigo", codigo));
            }

            if (!string.IsNullOrEmpty(descricao))
            {
                criteria.CreateAlias("Pessoa", "Pessoa")
                .Add(Restrictions.Like("Pessoa.NomeRazaoSocial", descricao, MatchMode.Anywhere));
            }

            if ((!string.IsNullOrEmpty(cargoCodigo)) || (!string.IsNullOrEmpty(cargoDescricao)))
            {
                criteria.CreateAlias("Cargo", "Cargo");
            }

            if (!string.IsNullOrEmpty(cargoCodigo))
            {

                criteria.Add(Restrictions.Eq("Cargo.Codigo", cargoCodigo));
            }

            if (!string.IsNullOrEmpty(cargoDescricao))
            {

                criteria.Add(Restrictions.Like("Cargo.Descricao", cargoDescricao, MatchMode.Anywhere));
            }

            if ((!string.IsNullOrEmpty(setorCodigo)) || (!string.IsNullOrEmpty(setorDescricao)))
            {
                criteria.CreateAlias("Setor", "Setor");
            }

            if (!string.IsNullOrEmpty(setorCodigo))
            {

                criteria.Add(Restrictions.Eq("Setor.Codigo", setorCodigo));
            }

            if (!string.IsNullOrEmpty(setorDescricao))
            {

                criteria.Add(Restrictions.Like("Setor.Descricao", setorDescricao, MatchMode.Anywhere));
            }

            if (previsaoSalarialDe > 0)
            {
                criteria.Add(previsaoSalarialAte >= previsaoSalarialDe
                    ? Restrictions.Between("PrevisaoSalarial", previsaoSalarialDe, previsaoSalarialAte)
                    : Restrictions.Eq("PrevisaoSalarial", previsaoSalarialDe));
            }

            if (salarioAnteriorDe > 0)
            {
                criteria.Add(salarioAnteriorAte >= salarioAnteriorDe
                    ? Restrictions.Between("SalarioAnterior", salarioAnteriorDe, salarioAnteriorAte)
                    : Restrictions.Eq("SalarioAnterior", salarioAnteriorDe));
            }

            if (percentualUltimoReajusteDe > 0)
            {
                criteria.Add(percentualUltimoReajusteAte >= percentualUltimoReajusteDe
                    ? Restrictions.Between("PercentualUltimoReajuste", percentualUltimoReajusteDe, percentualUltimoReajusteAte)
                    : Restrictions.Eq("PercentualUltimoReajuste", percentualUltimoReajusteDe));
            }

            if (ultimoReajusteDe.HasValue)
            {
                criteria.Add(ultimoReajusteAte.HasValue
                    ? Restrictions.Between("DataUltimoReajuste", ultimoReajusteDe.Value.Date, ultimoReajusteAte.Value.Date)
                    : Restrictions.Eq("DataUltimoReajuste", ultimoReajusteDe.Value.Date));
            }

            if (contratacaoDe.HasValue) 
            {
                criteria.Add(contratacaoAte.HasValue
                    ? Restrictions.Between("DataContratacao", contratacaoDe.Value.Date, contratacaoAte.Value.Date)
                    : Restrictions.Eq("DataContratacao", contratacaoDe.Value.Date));
            }

            if (demissaoDe.HasValue)
            {
                criteria.Add(demissaoAte.HasValue
                    ? Restrictions.Between("DataDemissao", demissaoDe.Value.Date, demissaoAte.Value.Date)
                    : Restrictions.Eq("DataDemissao", demissaoDe.Value.Date));
            }


            list = criteria.List<Funcionario>() as List<Funcionario>;

            return list;
        }

        public IList<Funcionario> ObterPorDescricao(int inicio, int quantidade, int quantidadeMinima, string descricao)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
            .SetFirstResult(inicio).SetMaxResults(quantidade);
               criteria.CreateAlias("Pessoa", "Pessoa")
               .Add(Restrictions.Like("Pessoa.NomeRazaoSocial", descricao, MatchMode.Anywhere));
            return criteria.List<Funcionario>() as List<Funcionario>;
        }

        public Funcionario ObterPorCpf(string cpf)
        {
             ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
                .CreateAlias("Pessoa", "Pessoa")
                .Add(Restrictions.Eq("Pessoa.CpfCnpj",cpf));
            return criteria.UniqueResult<Funcionario>();
        }

        public Funcionario ObterPorPessoa(Pessoa pessoa)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario))
               .Add(Restrictions.Eq("Pessoa", pessoa));
            return criteria.UniqueResult<Funcionario>();
        }

        public int ObterUltimoIdCodigoInteiro()
        {
            string[] literal = new string[] 
                {"a","b","c","d","e","f","g","h","i","j"
                ,"l","m","n","o","p","q","r","s","t","u","v","x","z","y"
                ,"w"};

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Funcionario)).SetMaxResults(1);

            for (int i = 0; i <= literal.Length - 1; i++)
            {
                criteria.Add(Restrictions.Not(Restrictions.Like("Codigo", literal[i], MatchMode.Anywhere)));
            }

            criteria.AddOrder(Order.Desc("FuncionarioId"));


            Funcionario funcionario = criteria.UniqueResult<Funcionario>();
            int ultimoCodigo = funcionario != null ? funcionario.FuncionarioId : 0;

            return ultimoCodigo;
        }
    }
}